package fetcher

import (
	"bufio"
	"fmt"
	"golang.org/x/net/html/charset"
	"golang.org/x/text/encoding"
	"golang.org/x/text/encoding/unicode"
	"golang.org/x/text/transform"
	"io/ioutil"
	"log"
	"net/http"
	"strings"
	"time"
)

// 获取页面编码
func determineEncoding(reader *bufio.Reader) encoding.Encoding {
	bytes, err := reader.Peek(1024)
	if err != nil {
		log.Printf("Fetcher encoding error:%v",err)
		// 返回UTF-8
		return unicode.UTF8
	}
	encoding, _, _ := charset.DetermineEncoding(bytes, "")
	return encoding
}

func fetchByResponse(url string,response *http.Response) ([]byte,error){
	strings.Replace(url,"http://","https://",1)
	request, err := http.NewRequest(http.MethodGet, url, nil)
	if err != nil {
		return nil,err
	}
	request.Header.Add("user-agent",
		`Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.164 Safari/537.36`)
	httpClient := &http.Client{}
	for _,cookie:=range response.Cookies(){
		request.AddCookie(cookie)
	}
	res, err := httpClient.Do(request)
	if err != nil {
		return nil, err
	}
	defer res.Body.Close()
	return handleResponse(url,res)
}

var rateLimiter = time.Tick(10*time.Millisecond)

func Fetch(url string) ([]byte,error){
	<- rateLimiter
	// response, err := http.Get(url)
	strings.Replace(url,"http://","https://",1)
	request, err := http.NewRequest(http.MethodGet, url, nil)
	if err != nil {
		return nil,err
	}
	request.Header.Add("user-agent",
		`Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.164 Safari/537.36`)
	httpClient := &http.Client{
	}
	response, err := httpClient.Do(request)
	if err != nil {
		return nil, err
	}
	defer response.Body.Close()
	return handleResponse(url,response)

}

func handleResponse(url string,response *http.Response) ([]byte,error) {
	if response.StatusCode != http.StatusOK{
		//if response.StatusCode == http.StatusAccepted {
		//	fetchByResponse(url, response)
		//}
		fmt.Println("Response ERROR:",response.StatusCode)
		return nil,fmt.Errorf("wrong status code:%d",response.StatusCode)
	}

	bodyReader:= bufio.NewReader(response.Body)
	encoding := determineEncoding(bodyReader)
	reader := transform.NewReader(bodyReader, encoding.NewDecoder())
	return ioutil.ReadAll(reader)
}
